package ofxdownloader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * Builds a String containing the content of an OFX request by combining
 * separate parts of the request together
 * @author Alex Spurling / Chris Thornton
 *
 */
public class OFXRequestBuilder {

	private static final String NW_ORG = "MFS_ORG";
	private static final String NW_FID = "MFS_FID";

	/**
	 * Returns the OFX header.
	 * @param oldFileID
	 * @param newFileID
	 * @return
	 */
	public static String getOFXHeader(String oldFileID, String newFileID) {
		if (oldFileID == null) oldFileID = "NONE";
		if (newFileID == null) newFileID = "NONE";
		return
		"OFXHEADER:100\n" +
		"DATA:OFXSGML\n" +
		"VERSION:102\n" +
		"SECURITY:NONE\n" +
		"ENCODING:USASCII\n" +
		"CHARSET:1252\n" +
		"COMPRESSION:NONE\n" +
		"OLDFILEUID:" + oldFileID + "\n" +
		"NEWFILEUID:" + newFileID + "\n";
	}

	/**
	 * Returns the OFX tags to make a sign on request
	 * @param userID
	 * @param userPass
	 * @return
	 */
	public static String getSignOnRequest(String userID, String userPass) {
		return
		"<SIGNONMSGSRQV1>\n" +
		"<SONRQ>\n" +
		"<DTCLIENT>" + getCurDate() + "\n" +
		"<USERID>" + userID + "\n" +
		"<USERPASS>" + userPass + "\n" +
		"<LANGUAGE>ENG\n" +
		"<FI>\n" +
		"<ORG>" + NW_ORG + "\n" +
		"<FID>" + NW_FID + "\n" +
		"</FI>\n" +
		"<APPID>Money\n" +
		"<APPVER>1400\n" +
		"</SONRQ>\n" +
		"</SIGNONMSGSRQV1>\n";
	}

	/**
	 * Returns the OFX tags to request an account list
	 * @return
	 */
	public static String getAccountListRequest() {
		return
		"<SIGNUPMSGSRQV1>\n" +
		"<ACCTINFOTRNRQ>\n" +
		"<TRNUID>" + generateID() + "\n" +
		"<ACCTINFORQ>\n" +
		"<DTACCTUP>19700101000000\n" + //The date that we last received the account list
		"</ACCTINFORQ>\n" +
		"</ACCTINFOTRNRQ>\n" +
		"</SIGNUPMSGSRQV1>\n";
	}

	/**
	 * Returns the OFX tags for making a statement request. These can be combined into
	 * a single request to retrieve statement transactions from multiple accounts
	 * @param account
	 * @param fromDate
	 * @param toDate
	 * @return
	 */
	public static String getStatementRequest(Account account, Date fromDate, Date toDate) {
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
		String fromDateTag = "";
		if (fromDate != null) fromDateTag = "<DTSTART>" + format.format(fromDate) + "\n";
		String toDateTag = "";
		if (toDate != null) toDateTag = "<DTEND>" + format.format(toDate) + "\n";

		return account.getAccountOFXRequest(generateID(), fromDateTag, toDateTag);
	}

	/**
	 * Completes a request by combining the header with the body and ensuring
	 * the body is contained in <OFX></OFX> tags
	 * @param header
	 * @param body
	 * @return
	 */
	public static String getCompleteRequest(String header, String body) {
		if (body != null && !body.startsWith("<OFX>") && !body.endsWith("</OFX>\n")) {
			body = "<OFX>\n" + body + "</OFX>\n";
		}
		return header + "\n" + body;
	}

	/**
	 * Returns the current date in the format yyyyMMddHHmmss eg
	 * 20080613230844
	 * @return
	 */
	private static String getCurDate() {
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		return format.format(new Date());
	}

	/**
	 * Generates a unique ID for keeping track of transaction requests
	 * @return
	 */
	public static String generateID() {
		return UUID.randomUUID().toString().toUpperCase();
	}

	/**
	 * Remove unique identifiers to make comparison of requests possible
	 * @param input
	 * @return
	 */
	public static String removeUIDs(String input) {
		return input.replaceAll("(?m)^.*UID.*$", "");
	}

	/**
	 * Remove current dates to make comparison of requests possible
	 * @param input
	 * @return
	 */
	public static String removeClientDates(String input) {
		return input.replaceAll("(?m)^.*<DTCLIENT>.*$", "");
	}
}
